<?php
declare (strict_types = 1);
namespace app\common\model\content;

use app\admin\traits\GetTableData;
use app\common\utils\facade\FileUtil;
use think\Model;
use app\common\model\user\User;
use app\common\model\message\Comment;
use app\common\model\message\Like;

/**
 * @mixin think\Model
 */
class Article extends Model
{
    use GetTableData;

    const STATUS_PUB = 1; //发布状态
    const STATUS_DRA = 2; //草稿
    const STATUS_TRA = 3; //回收站

    //使用到的场景
    const SCENE_NORMAL = 'normal';
    const SCENE_TOPIC = 'topic';

    //图片上传字段与目录
    const UP_FIELD = 'article_cover';
    const UP_FOLDER = 'article';

    //是否精品
    const BEST_NO = 1;
    const BEST_YES = 2;

    // 设置字段信息
    protected $schema = [
        'id'           => 'int',
        'title'        => 'string',
        'brief'        => 'string',
        'image'        => 'string',
        'status'       => 'int',
        'best'         => 'int',
        'disallow'     => 'int',
        'liked'        => 'int',
        'visited'      => 'int',
        'commented'    => 'int',
        'user_id'      => 'int',
        'topic_id'     => 'int',
        'category_id'  => 'int',
        'create_time'  => 'int',
        'update_time'  => 'int',
    ];

    //类型自动转换
    protected $type  = [
        'id'         => 'integer',
        'status'     => 'integer',
        'best'       => 'integer',
        'disallow'   => 'integer',
        'liked'      => 'integer',
        'visited'    => 'integer',
        'commented'  => 'integer',
        'user_id'    => 'integer',
        'topic_id'   => 'integer',
        'category_id'=> 'integer',
    ];

    //插入之前完善数据
    public static function onBeforeInsert(Model $model)
    {
        $model->setAttr('user_id',app()->user->getId());
    }

    //保存之前转移图片到永久地址
    public static function onBeforeWrite(Model $model){
        //修改话题(如果修改了图片 就先删除原有图片
        //删除原来图片
        if ($model->isExists() && array_key_exists('image', $model->getChangedData())){
            $real_file = static::getRealPath($model->getOrigin('image'));
            if (is_file($real_file)) FileUtil::unlinkFile($real_file);
        }
        //移动到永久目录
        if(!empty($model->image) && ( !$model->isExists() || array_key_exists('image', $model->getChangedData()))){
            $ori_img = static::getTmpPath($model->image);
            $des_img = static::getRealPath($model->image);

            if(is_file($ori_img)){
                if ( !FileUtil::moveFile($ori_img, $des_img) )
                    return false;
            }
        }
        return true;
    }


    //删除之前
    public static function onBeforeDelete(Model $model)
    {
        //删除失去关联的无用标签
        Tag::cleanTags($model->id);

        //删除文章内容图片
        return Image::destroy(function($query) use ($model){
            $query->where(['article_id' => $model->id]);
        });



    }
    //删除之后
    public static function onAfterDelete(Model $model)
    {

        //删除文章封面
        if ( !empty($model->image) && !$model->isAutoImage()){
            $real_file = static::getRealPath($model->image);
            if(is_file($real_file)) FileUtil::unlinkFile($real_file);
        }

        //删除评论
        Comment::destroy(function($query) use ($model){
            $query->where('article_id','=',$model->id);
        });

        //删除收藏
        Like::destroy(function($query) use ($model){
            $query->where('article_id','=',$model->id);
        });

        return true;
    }

    //获取临时文件的绝对路径
    private static function getTmpPath($file){
        if (empty($file)) return '';
        return config('filesystem.disks.local.root') . DS. $file;
    }
    //获取永久文件的绝对路径
    private static function getRealPath($file){
        if (empty($file)) return '';
        return config('filesystem.disks.public.root') .DS. $file;
    }

    //判断当前封面是手动设置还是自动生成
    public function isAutoImage(){
        return $this->getAttr('image') && strpos($this->getAttr('image'), '/') === 0;
    }

    //属性获取器 封面获取器(页面显示图片)
    public function getImageUrlAttr()
    {
        if (strpos($this->getAttr('image'),'/') === 0)
            return $this->getAttr('image');
        return empty($this->getAttr('image')) ? '' : showImg($this->getAttr('image'));
    }

    public function getTagsStrAttr()
    {
        $str = '';
        foreach ($this->getAttr('tags') as $item){

            $str .= trim($item->getAttr('name')) . ',';
        }

        return trim($str, ',');
    }

    //定义关联数据
    //关联用户名称
    public function user()
    {
        return $this->belongsTo(User::class,'user_id', 'id')->bind([
            'username' => 'showName',
            'avatar' => 'avatarUrl'
        ]);
    }
    //关联分类
    public function category()
    {
        return $this->belongsTo(Category::class,'category_id', 'id')->bind([
            'category_name' => 'name'
        ]);
    }
    //关联话题
    public function topic()
    {
        return $this->belongsTo(Topic::class,'topic_id', 'id')->bind([
            'topic_name' => 'name'
        ]);
    }
    //关联内容
    public function content()
    {
        return $this->hasOne(Content::class,'article_id', 'id')->bind([
            'article_content'=>'content'
        ]);
    }
    //直接获取关联内容
    public function getContent(){
        return Content::where('article_id', '=', $this->getAttr('id'))->value('content');
    }
    //关联图片
    public function images()
    {
        return $this->hasMany(Image::class,'article_id', 'id');
    }
    //关联标签
    public function tags()
    {
        return $this->belongsToMany(Tag::class, ArticleTag::class);
    }
    //关联评论
    public function comments()
    {
        return $this->hasMany(Comment::class,'article_id', 'id');
    }
    //关联评论
    public function likes()
    {
        return $this->hasMany(Like::class,'article_id', 'id');
    }



    /**
     * 获取文章列表（datatable 数据）
     */
    public static function getListData(array $ruleWhere = []){
        //要查询的字段
        $fields = [
            'fields' =>['id','title','status','best','disallow','visited','category_id','topic_id','user_id','create_time','update_time'],
            'with' => ['category','topic','user'],
            'withCount' => ['comments','likes'],
        ];

        //(构建查询条件)
        $where = [];
        if ($start = input('start_time')){
            $where[] = ['create_time', '>=', strtotime($start)];
        }
        if ($end = input('end_time')){
            $where[] = ['create_time', '<=', strtotime( $end)];
        }
        if ($title = input('title')){
            $where[] = ['title','like','%'.$title.'%'];
        }
        if ($cat = input('category_id/d')){
            $where[] = ['category_id','=',$cat];
        }
        if (( $topic = input('topic_id/d' )) !== null){
            $where[] = ['topic_id','=',$topic];
        }
        if ($status = input('status/d')){
            $where[] = ['status','=',$status];
        }



        //排序
        $order = ['id'=>'desc','create_time'=>'desc'];

        //[count:查询到的数目, list:记录列表]
        return static::operateDatum($where, $fields, $order, $ruleWhere);

    }


    /**
     * #判断指定话题下是否包含未发布的文章(草稿 回收站)
     * @param $topic_id
     * @return bool
     */
    public static function hasTraOrDra(int $topic_id){
        if ($topic_id <= 0) return false;
        return (bool) static::where([
            ['topic_id', '=', $topic_id],
            ['status', '<>', static::STATUS_PUB]
        ])->count();
    }

    /**
     * #获取指定话题下包含多少篇文章
     * @param int $topic_id
     * @return int
     */
    public static function counterByTopic(int $topic_id){
        if ($topic_id <= 0) return false;
        return static::where([
           'topic_id' => $topic_id
        ])->count();
    }

    /**
     * #更新文章封面
     * @param int $id
     * @return Article|bool
     */
    public static function UpdateImage(int $id){
        if ($id <= 0) return false;
        return static::update([
            'image' => Image::where(['article_id'=>$id])->order(['create_time'=>'ASC','id'=>'ASC'])->value('image'),
        ],['id'=>$id]);
    }

}
